/**文件系统操作 */
import * as Fs from "fs";
/**路径系统操作类 */
import * as Path from "path";
/**基础数据处理 */
import MBase from "./m-base";

/**读取目录 */
const readDir = (path: string): Promise<Array<string>> => {
  return new Promise((resolve, reject) => {
    Fs.readdir(path, (err: any, files: Array<string>) => {
      if (err) return reject(err);
      resolve(files);
    });
  });
};
/**创建目录 */
const createPath = (path: string): Promise<void> => {
  return new Promise((resolve, reject) => {
    if (Fs.existsSync(path)) resolve(void 0);
    Fs.mkdir(path, { recursive: true }, (err: any) => {
      if (err) return reject(err);
      resolve(void 0);
    });
  });
};

/**读取文件内容 */
const readFile = (file: string): Promise<string> => {
  return new Promise((resolve, reject) => {
    Fs.readFile(file, (err: any, data: Buffer) => {
      if (err) return reject(err);
      resolve(data.toString());
    });
  });
};
/**写入文件内容 */
const writeFile = (path: string, data: string): Promise<void> => {
  return new Promise((resolve, reject) => {
    Fs.writeFile(path, data, (err: any) => {
      if (err) return reject(err);
      resolve(void 0);
    });
  });
};
/**添加文件内容 */
const appendFile = (path: string, data: string): Promise<void> => {
  return new Promise((resolve, reject) => {
    Fs.appendFile(path, data, (err: any) => {
      if (err) return reject(err);
      resolve(void 0);
    });
  });
};
/**删除文件 */
const deleteFile = (path: string): Promise<void> => {
  return new Promise((resolve, reject) => {
    if (!Fs.existsSync(path)) resolve(void 0);
    Fs.unlink(path, (err: any) => {
      if (err) return reject(err);
      resolve(void 0);
    });
  });
};

/**文件路径处理 */
export default class MFile {
  /**获取命令项目根目录 */
  public static getRoot() {
    return MFile.getPath(MFile.getPath(__dirname));
  }
  /**获取文件或目录名称 */
  public static getName(path: string, ext: boolean = true) {
    const name = Path.basename(path);
    if (ext) return name;
    return name.split(".")[0];
  }

  /**获取文件或目录的上级目录路径 */
  public static getPath(path: string) {
    return Path.dirname(path);
  }

  /**组装网络路径 */
  public static joinUrlPath(...paths: Array<string>) {
    paths = paths.map((x) => MBase.trimStr(x, "/"));
    paths = paths.filter((x) => !!x);
    return paths.join("/");
  }

  /**组装文件或者目录路径 */
  public static joinDirPath(...paths: Array<string>) {
    paths = paths.filter((x) => !!x);
    paths = paths.map((x) => x.replace(/\//, Path.sep));
    return Path.join(...paths);
  }

  /**地址是否存在 */
  public static isExist(path: string) {
    return Fs.existsSync(path);
  }

  /**地址是否一个文件 */
  public static isFile(path: string) {
    if (!MFile.isExist(path)) return false;
    return Fs.statSync(path).isFile();
  }

  /**是否一个文件夹 */
  public static isDir(path: string) {
    if (!MFile.isExist(path)) return false;
    return Fs.statSync(path).isDirectory();
  }

  /**文件内容读取 */
  public static async readFile(file: string) {
    return await readFile(file);
  }

  /**文件写内容 */
  public static async writeFile(path: string, data: string) {
    if (!MFile.isExist(Path.dirname(path))) {
      await MFile.createPath(Path.dirname(path));
    }
    return await writeFile(path, data);
  }

  /**文件添加内容[没文件会异常] */
  public static async appendFile(path: string, data: string) {
    if (!MFile.isExist(Path.dirname(path))) {
      await MFile.createPath(Path.dirname(path));
    }
    return await appendFile(path, data);
  }

  /**文件删除 */
  public static async deleteFile(path: string) {
    return await deleteFile(path);
  }

  /**创建目录 */
  public static async createPath(path: string) {
    return await createPath(path);
  }

  /**读取目录 */
  public static async readDir(path: string) {
    return await readDir(path);
  }

  /**删除目录 */
  public static async deletePath(path: string) {
    if (!MFile.isExist(path)) return;
    if (MFile.isFile(path)) return await MFile.deleteFile(path);
    const childs = await MFile.readDir(path); //读取目录
    for (let i = 0; i < childs.length; i++) {
      const curPath = Path.join(path, childs[i]); //当前地址
      if (MFile.isDir(curPath)) {
        await MFile.deletePath(curPath); //递归删除目录
      } else if (MFile.isFile(curPath)) {
        await MFile.deleteFile(curPath); //删除文件
      }
    }
    Fs.rmdirSync(path); //删除空目录
  }

  /**检查路径，没有则创建[有则清空] */
  public static async checkPath(path: string, del: boolean = false) {
    if (del && MFile.isDir(path)) return await MFile.deletePath(path);
    if (!MFile.isDir(path)) await MFile.createPath(path);
  }
}
